<template>
  <!-- 高德地图示例 -->
  <div style="height:100%">
    <!-- <div style="height:60px;">
      <el-form :inline="true" :model="ruleForm">
        <el-form-item label="设备号" prop="devId">
          <el-input v-model.trim="ruleForm.devId" placeholder="请填写设备号">
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="showList"
            :loading="btnLoading">查询</el-button>
        </el-form-item>
        <el-form-item v-if="track.flag">
          <el-divider direction="vertical"
            style="height: 100%;"></el-divider>
          <span style="color:red;">有且仅有一个设备，正在实时规划轨迹！</span>
        </el-form-item>
      </el-form>
    </div> -->

    <div id="container" style="height:100%"></div>
  </div>
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader';
import { postAction, getAction } from '@/api/manage';
export default {
  components: {},
  data() {
    return {
      //搜索相关参数
      ruleForm: {
        devId: '',
        en: '',
      },
      showSearch: false,
      btnLoading: false,
      //定义AMap
      AMap: null,
      AMapUI: null,
      //轨迹（当前设备有且仅有一个才会显示轨迹）
      track: {
        flag: false, //当前列表是否只有一个
        devId: '', //当前设备id
        lineArr: [], //轨迹数组
      },
    };
  },
  mounted() {
    //初始化地图
    this.initMap();
  },
  destroyed() {
    if (this.timer) {
      clearInterval(this.timer);
      console.log('关闭定时任务');
    }
    // 销毁地图，并清空地图容器.该方法执行后，地图对象被注销，内存释放，地图容器被清空。
    this.map.destroy();
  },
  methods: {
    //初始化地图
    initMap() {
      window._AMapSecurityConfig = {
        securityJsCode: this.AMapSecurityJsCode,
      };
      AMapLoader.load({
        key: this.AMapKey, // 申请好的Web端开发者Key，首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
        plugins: [], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
        AMapUI: {
          version: '1.1',
          plugins: ['overlay/SimpleMarker'],
        },
      })
        .then(() => {
          this.AMap = AMap;
          this.AMapUI = AMapUI;
          console.log('AMap', this.AMap);
          console.log('AMapUI', this.AMapUI);

          //初始化地图容器
          this.map = new AMap.Map('container', {
            //设置地图容器id
            viewMode: '2D', //采用2D模式
            zoom: 5, //初始化地图级别
            center: [105.602725, 37.076636], //初始化地图中心点位置
            mapStyle: 'amap://styles/whitesmoke', //设置地图的显示样式
          });

          //展示【road:道路及道路标注、bg:区域面、point:兴趣点、building:建筑物】
          this.map.setFeatures(['road', 'bg', 'point']);

          //设置加载插件
          AMap.plugin(['AMap.ToolBar', 'AMap.Scale'], () => {
            //异步加载插件
            this.map.addControl(new AMap.ToolBar());
            this.map.addControl(new AMap.Scale());
          });

          //信息窗口设置
          this.infoWindow = new AMap.InfoWindow({
            offset: new AMap.Pixel(0, -4),
          });

          //初始化点标记，并创建定时任务
          this.showList();
          console.log('开启定时任务');
          this.timer = setInterval(() => {
            this.showList('timer');
          }, 1000 * 30);
        })
        .catch((e) => {
          console.log(e);
        });
    },
    /**
     * 获取设备列表
     */
    showList(from) {
      if (!from || from != 'timer') {
        this.btnLoading = true;
      }
      getAction('/device/queryDevBasicStateList', {
        devId: this.ruleForm.devId,
        en: this.ruleForm.en,
        tn: this.ruleForm.tn,
      })
        .then((res) => {
          if (res.code == 200) {
            //首先清空所有点标记
            this.clearAllMarker();
            //获取返回列表数据
            let devList = res.data;
            console.log('...devList', devList);

            //定义点标记数组
            let markerList = [];
            //定义所有点的经纬度（【'纬度1,经度1','纬度2,经度2'】）
            let points = [];
            for (let index = 0; index < devList.length; index++) {
              const element = devList[index];
              // console.log('element', element);
              let onlineState = element.onlineState;
              let iconImg;
              if (onlineState) {
                iconImg = require('@/assets/train-green.png');
              } else {
                iconImg = require('@/assets/train-solid.png');
              }
              // 创建一个 Marker 实例：
              let marker = new AMap.Marker({
                position: new AMap.LngLat(element.longitude, element.latitude),
                title: element.lineName,
                icon: new AMap.Icon({
                  image: iconImg,
                  imageSize: new AMap.Size(15, 21),
                }),
              });
              points[index] = element.latitude + ',' + element.longitude;

              //设置单击事件并组装内容
              this.setMarkerClick(marker, element);

              //添加到列表
              markerList[index] = marker;
            }
            //是否重新定义地图的center和zoom
            if (!from || from != 'timer') {
              //不是从定时任务中来的，需要重新定义center和zoom
              let centerPoint = this.getPointsCenter(points);
              let zoom = this.getZoom(points);
              this.map.setZoom(zoom);
              this.map.setCenter([centerPoint[1], centerPoint[0]]);
            }
            // 将创建的点标记添加到已有的地图实例：
            this.map.add(markerList);

            //判断是否需要填入轨迹
            this.handleTrack(devList);
          } else {
            this.$message.error(res.message);
          }
        })
        .catch((err) => {
          this.$message.error(err.message);
        })
        .finally(() => {
          this.btnLoading = false;
        });
    },
    /**
     * 设置单击事件
     */
    setMarkerClick(marker, element) {
      //在线离线处理
      let onlineHtml;
      if (element.onlineState) {
        onlineHtml = '<font color="green">在线</font>';
      } else {
        onlineHtml = '<font color="gray">离线</font>';
      }
      marker.content =
        `<p><b>设备号：</b>` +
        element.devId +
        `</p>
                <p><b>机车号：</b>` +
        element.en +
        `</p>
                <p><b>线路名称：</b>` +
        element.lineName +
        `</p>
                <p><b>gps时间：</b>` +
        element.gpsTime +
        `</p>
                <p><b>在线状态：</b>` +
        onlineHtml +
        `</p>
              `;
      marker.on('click', this.markerClick);
    },
    /**
     * 根据查询返回的数据处理轨迹
     * ==只有返回设备列表有且仅有一条时，才会填入轨迹
     * @param {*} devList 查询返回设备列表
     */
    handleTrack(devList) {
      if (!devList || devList.length == 0 || devList.length > 1) {
        this.track.flag = false;
        return;
      }
      const element = devList[0];
      let devId = element.devId;
      if (devId != this.track.devId) {
        //之前不是本设备的轨迹，清空并重新填入
        this.track.lineArr = [];
      }
      this.track.devId = devId;
      this.track.flag = true;
      this.track.lineArr.push(
        new this.AMap.LngLat(element.longitude, element.latitude)
      );

      //使用默认绘画
      if (this.track.lineArr.length > 1) {
        console.log('...开始画轨迹', this.track.lineArr);
        this.drawLine(element);
      }
    },
    /**
     * 画轨迹
     */
    drawLine(element) {
      this.AMap.convertFrom(this.track.lineArr, 'gps', (status, result) => {
        if (result.info === 'ok') {
          const paths = result.locations;
          this.map.clearMap();

          var distance = this.getDistanse(
            paths[paths.length - 1].lat,
            paths[0].lat,
            paths[paths.length - 1].lng,
            paths[0].lng
          );
          if (distance > 1) {
            //首尾距离大于1km才出来起始点标记
            var startIcon = new AMap.Icon({
              image: require('@/assets/start.png'),
              imageSize: new AMap.Size(19, 31),
            });
            this.startMarker = new AMap.Marker({
              map: this.map,
              position: paths[0], //起点经纬度
              offset: new AMap.Pixel(-9, -31),
              autoRotation: true,
              icon: startIcon,
            });
            this.map.add(this.startMarker);
          }

          //终点点标记
          var endIcon = new AMap.Icon({
            image: require('@/assets/train-solid.png'),
            imageSize: new AMap.Size(15, 21),
          });
          this.endMarker = new AMap.Marker({
            map: this.map,
            position: paths[paths.length - 1], //终点经纬度
            offset: new AMap.Pixel(-10, -10),
            autoRotation: true,
            icon: endIcon,
          });
          //设置单击事件并组装内容
          this.setMarkerClick(this.endMarker, element);
          this.map.add(this.endMarker);

          // 绘制轨迹
          var polyline = new AMap.Polyline({
            path: paths,
            showDir: true,
            strokeColor: '#28F', //线颜色
            strokeWeight: 6, //线宽
          });
          this.map.add(polyline);

          this.map.setFitView(); //自适应缩放级别
        }
      });
    },

    /**
     * 清空所有点标记
     * */
    clearAllMarker() {
      let newMarker = this.map.getAllOverlays('marker'); //获取所有的覆盖物
      newMarker.map((item) => {
        //根据自己的需求判断
        this.map.remove(item);
      });
    },
    //标记单击事件
    markerClick(e) {
      //获取当前点击的标记值
      this.infoWindow.setContent(e.target.content);
      this.infoWindow.open(this.map, e.target.getPosition());
    },
    //查询设备列表
    onSearch() {
      this.$refs.devDialogList.show('map');
    },
    //选择设备回调函数
    confirm(obj) {
      this.ruleForm.devId = obj.devId;
      this.ruleForm.en = obj.en;
    },
    /**
     * 参数数组points的每一项为每一个点的：纬度,经度
     * 如 points = ['30.86660,104.390740', '点的纬度,点的经度'……];
     * 返回中心点的数组[纬度,精度]
     */
    getPointsCenter(points) {
      var point_num = points.length; //坐标点个数
      var X = 0,
        Y = 0,
        Z = 0;
      for (let i = 0; i < points.length; i++) {
        if (points[i] == '') {
          continue;
        }
        let point = points[i].split(',');
        var lat, lng, x, y, z;
        lat = (parseFloat(point[0]) * Math.PI) / 180;
        lng = (parseFloat(point[1]) * Math.PI) / 180;
        x = Math.cos(lat) * Math.cos(lng);
        y = Math.cos(lat) * Math.sin(lng);
        z = Math.sin(lat);
        X += x;
        Y += y;
        Z += z;
      }
      X = X / point_num;
      Y = Y / point_num;
      Z = Z / point_num;

      var tmp_lng = Math.atan2(Y, X);
      var tmp_lat = Math.atan2(Z, Math.sqrt(X * X + Y * Y));

      return [(tmp_lat * 180) / Math.PI, (tmp_lng * 180) / Math.PI];
    },
    /**
     * 根据原始数据计算中心坐标和缩放级别，并为地图设置中心坐标和缩放级别。
     * 如 points = ['30.86660,104.390740', '点的纬度,点的经度'……];
     * */
    getZoom(points) {
      if (!points || points.length == 0) {
        return 5;
      }
      var maxLng = points[0].split(',')[1];
      var minLng = points[0].split(',')[1];
      var maxLat = points[0].split(',')[0];
      var minLat = points[0].split(',')[0];
      var res;
      for (var i = points.length - 1; i >= 0; i--) {
        let lng = points[i].split(',')[1];
        let lat = points[i].split(',')[0];
        res = {
          lng: lng,
          lat: lat,
        };
        if (res.lng > maxLng) maxLng = res.lng;
        if (res.lng < minLng) minLng = res.lng;
        if (res.lat > maxLat) maxLat = res.lat;
        if (res.lat < minLat) minLat = res.lat;
      }
      var zoom = [
        '50',
        '100',
        '200',
        '500',
        '1000',
        '2000',
        '5000',
        '10000',
        '20000',
        '25000',
        '50000',
        '100000',
        '200000',
        '500000',
        '1000000',
        '2000000',
      ]; //级别18到3。
      //获取两点距离,保留小数点后两位
      var distance = this.getDistanse(maxLat, minLat, maxLng, minLng);
      if (distance > 1000) {
        return 4;
      } else if (distance >= 500 && distance < 1000) {
        return 5;
      } else if (distance >= 200 && distance < 5000) {
        return 6;
      } else if (distance >= 100 && distance < 200) {
        return 7;
      } else if (distance >= 50 && distance < 100) {
        return 8;
      } else {
        return 10;
      }
    },
    // 获取坐标极值之间的距离double，单位km
    getDistanse(lat1, lat2, lng1, lng2) {
      //根据坐标，地球半径算出两个坐标之间的距离
      let radLat1 = (lat1 * Math.PI) / 180;
      let radLat2 = (lat2 * Math.PI) / 180;
      let radLon1 = (lng1 * Math.PI) / 180;
      let radLon2 = (lng2 * Math.PI) / 180;
      let a = radLat1 - radLat2;
      let b = radLon1 - radLon2;
      let s =
        2 *
        Math.asin(
          Math.sqrt(
            Math.pow(Math.sin(a / 2), 2) +
              Math.cos(radLat1) *
                Math.cos(radLat2) *
                Math.pow(Math.sin(b / 2), 2)
          )
        );
      s = s * 6378.137;
      s = Math.round(s * 10000) / 10000;
      return s;
    },
  },
};
</script>

<style lang="scss" scoped>
#container {
  padding: 0px;
  margin: 0px;
  width: 100%;
}
</style>